package view.inventory;

import com.toedter.calendar.JDateChooser;
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.text.MaskFormatter;
import main.ServicesList;
import model.inventory.Hadiah;
import model.inventory.Item;
import model.inventory.ItemBonus;
import model.inventory.ItemDiskon;
import model.inventory.ItemHpp;
import model.inventory.ItemSupplier;
import model.inventory.Unit;
import model.publics.Supplier;
import org.apache.log4j.Logger;
import utility.Constants;
import utility.NameValueList;
import utility.StringUtils;
import utility.com.ComponentUtils;
import utility.com.TableUtil;
import utility.com.TextComponentUtils;
import utility.typeSafe.DiskonType;
import utility.typeSafe.EnumUtils;
import utility.typeSafe.HitungBonus;
import utility.typeSafe.ItemStatus;
import utility.typeSafe.JenisBonus;
import utility.typeSafe.SatuanBonus;
import view.lookup.LookupSimpleFrm;

public class ItemHppFrm extends javax.swing.JFrame {

    private static final int COL_DISKON_JENIS       = 0;
    private static final int COL_DISKON_JUMLAH      = 1;
    private static final int COL_DISKON_STARTDATE   = 2;
    private static final int COL_DISKON_ENDDATE     = 3;
    
    private static final int COL_BONUS_HITUNG   = 0;
    private static final int COL_BONUS_JENIS    = 1;
    private static final int COL_BONUS_SATUAN   = 2;
    private static final int COL_BONUS_BATAS    = 3;
    private static final int COL_BONUS_JUMLAH   = 4;
    private static final int COL_BONUS_STARTDATE= 5;
    private static final int COL_BONUS_ENDDATE  = 6;
    private static final int COL_BONUS_ITEM     = 7;
    private static final DateFormat dateFormat = new SimpleDateFormat("dd/mm/yyyy");
    
    final JTextField diskonCellEditor = new JTextField();
    final JFormattedTextField diskonStartDateCellEditor = new JFormattedTextField(dateFormat);
    final JFormattedTextField diskonEndDateCellEditor = new JFormattedTextField(dateFormat);
    final JTextField bonusCellEditor = new JTextField();
    final JTextField bonusBatasCellEditor = new JTextField();
    final JTextField bonusItemCellEditor = new JTextField();
    final JFormattedTextField bonusStartDateCellEditor = new JFormattedTextField(dateFormat);
    final JFormattedTextField bonusEndDateCellEditor = new JFormattedTextField(dateFormat);
    
    final JComboBox cmbDiskonJenis = new JComboBox();
    final JComboBox cmbBonusHitung = new JComboBox();
    final JComboBox cmbBonusSatuan = new JComboBox();
    final JComboBox cmbBonusJenis = new JComboBox();

    private List<NameValueList> statusList = EnumUtils.enumToNameValueList(ItemStatus.class);
    private List<NameValueList> diskonTypeList = EnumUtils.enumToNameValueList(DiskonType.class);
    private List<NameValueList> hitungList = EnumUtils.enumToNameValueList(HitungBonus.class);
    private List<NameValueList> satuanList = EnumUtils.enumToNameValueList(SatuanBonus.class);
    private List<NameValueList> jenisBonusList = EnumUtils.enumToNameValueList(JenisBonus.class);
    
    private ItemDiskonTM diskonTM;
    private ItemBonusTM bonusTM;
    private ItemHpp itemHpp;
    private Supplier supplier;
    private ItemListener itemListener = new StartDatesListener();

    private static Logger log = Logger.getLogger(ItemHppFrm.class);
    private Object oldValue, newValue;
    
    public ItemHppFrm() {
        initComponents();
        initComponentsRules();
    }

    public void execute(boolean withVisible, int id) {
        setLocationRelativeTo(null);
        initForm();
        if (withVisible) { setVisible(true); }
    }
        
    private void initGrid(){
        DefaultTableCellRenderer rightCellRender = new DefaultTableCellRenderer();
        rightCellRender.setHorizontalAlignment(SwingConstants.RIGHT);
        //GRID DISKON
        diskonTM = new ItemDiskonTM(itemHpp.getItemDiskons());
        gridDiskon.setModel(diskonTM);
        
        //set alignment
        gridDiskon.getColumnModel().getColumn(COL_DISKON_JUMLAH).setCellRenderer(rightCellRender);
            
        //cell ony accept number    
        TextComponentUtils.setCurrency(diskonCellEditor);
        gridDiskon.getColumnModel().getColumn(COL_DISKON_JUMLAH).setCellEditor(new DefaultCellEditor (diskonCellEditor));
        gridDiskon.getColumnModel().getColumn(COL_DISKON_STARTDATE).setCellEditor(new DefaultCellEditor (diskonStartDateCellEditor));
        gridDiskon.getColumnModel().getColumn(COL_DISKON_ENDDATE).setCellEditor(new DefaultCellEditor (diskonEndDateCellEditor));
        
        //combobox
        cmbDiskonJenis.setModel(ComponentUtils.getDefaultComboBoxModel(diskonTypeList));
        gridDiskon.getColumnModel().getColumn(COL_DISKON_JENIS).setCellEditor(new DefaultCellEditor (cmbDiskonJenis));
        
        //GRID BONUS
        bonusTM = new ItemBonusTM(itemHpp.getItemBonuses());
        gridBonus.setModel(bonusTM);
        
        //set alignment
        TextComponentUtils.setNumericTextOnly(bonusBatasCellEditor);
        TextComponentUtils.setNumericTextOnly(bonusCellEditor);
        gridBonus.getColumnModel().getColumn(COL_BONUS_BATAS).setCellRenderer(rightCellRender);
        gridBonus.getColumnModel().getColumn(COL_BONUS_JUMLAH).setCellRenderer(rightCellRender);
        
        // gridDiskon.setDefaultEditor(Date.class, new JDateChooserCellEditor());
              
        //combobox
        cmbBonusHitung.setModel(ComponentUtils.getDefaultComboBoxModel(hitungList));
        cmbBonusSatuan.setModel(ComponentUtils.getDefaultComboBoxModel(satuanList));
        cmbBonusJenis.setModel(ComponentUtils.getDefaultComboBoxModel(jenisBonusList));
        gridBonus.getColumnModel().getColumn(COL_BONUS_HITUNG).setCellEditor(new DefaultCellEditor (cmbBonusHitung));
        gridBonus.getColumnModel().getColumn(COL_BONUS_SATUAN).setCellEditor(new DefaultCellEditor (cmbBonusSatuan));
        gridBonus.getColumnModel().getColumn(COL_BONUS_JENIS).setCellEditor(new DefaultCellEditor (cmbBonusJenis));
        gridBonus.getColumnModel().getColumn(COL_BONUS_STARTDATE).setCellEditor(new DefaultCellEditor (bonusStartDateCellEditor));
        gridBonus.getColumnModel().getColumn(COL_BONUS_ENDDATE).setCellEditor(new DefaultCellEditor (bonusEndDateCellEditor));
        gridBonus.getColumnModel().getColumn(COL_BONUS_ITEM).setCellEditor(new DefaultCellEditor (bonusItemCellEditor));
         
        //gridBonus.setDefaultEditor(Date.class, new JDateChooserCellEditor());
        gridBonus.getColumnModel().getColumn(COL_BONUS_HITUNG).setPreferredWidth(25);
        gridBonus.getColumnModel().getColumn(COL_BONUS_SATUAN).setPreferredWidth(25);
        gridBonus.getColumnModel().getColumn(COL_BONUS_BATAS).setPreferredWidth(20);
        gridBonus.getColumnModel().getColumn(COL_BONUS_JUMLAH).setPreferredWidth(20);
        gridBonus.getColumnModel().getColumn(COL_BONUS_JENIS).setPreferredWidth(25);
        gridBonus.getColumnModel().getColumn(COL_BONUS_STARTDATE).setPreferredWidth(45);
        gridBonus.getColumnModel().getColumn(COL_BONUS_ENDDATE).setPreferredWidth(45);
    }
    
    private void initForm(){
        itemHpp = new ItemHpp();
        supplier = new Supplier();
        itemHpp.getId().setStartDate(new Date());
        txtDiskon.setText("0");
        txtFraksi.setText("1");
        txtHarga.setText("0");
        txtItemName.setText("");
        txtHpp.setText("0");
        txtTop.setText("0");
        txtKode.setText("00419");
        txtNet.setText("0");
        txtPpn.setText("0");
        txtSpl.setText("P.01");
        txtSuplierName.setText("");
        txtUnit.setText("");
        
        cmbKondisi.setSelectedItem(0);
        dtpStartDate.setDate(StringUtils.truncDate(new Date()));
        initGrid();
        initButtonState(false);
    }
    
    private void saveData() {
        itemHpp.getId().setStartDate(StringUtils.truncDate(dtpStartDate.getDate()));
        itemHpp.setFraksi(Integer.parseInt(txtFraksi.getText()));
        itemHpp.setTop(Integer.parseInt(txtTop.getText()));
        itemHpp.setPrice(TextComponentUtils.parseNumberToBigDecimal((String)txtHarga.getText()));
        itemHpp.setDiskon(TextComponentUtils.parseNumberToBigDecimal((String)txtDiskon.getText()));
        itemHpp.setPpn(TextComponentUtils.parseNumberToBigDecimal((String)txtPpn.getText()));
        itemHpp.setHpp(TextComponentUtils.parseNumberToBigDecimal((String)txtHpp.getText()));
        itemHpp.setHppAfterPpn(TextComponentUtils.parseNumberToBigDecimal((String)txtNet.getText()));
        itemHpp.setKondisiBarang(((NameValueList) cmbKondisi.getSelectedItem()).getKey());
        
        List<Integer> emptyItem = new ArrayList<>();
        
        //remove diskon 0
        for (int i=0; i<itemHpp.getItemDiskons().size(); i++) {
            BigDecimal dis = itemHpp.getItemDiskons().get(i).getDiskon();
            if (dis.compareTo(BigDecimal.ZERO) < 1) {emptyItem.add(i); }
        }
        
        for (Integer i: emptyItem) {
            int idx = i;
            itemHpp.getItemDiskons().remove(idx);
        }
        
        //remove diskon 0
        emptyItem.clear();
        for (int i=0; i<itemHpp.getItemBonuses().size(); i++) {
            if (itemHpp.getItemBonuses().get(i).getBonus() < 1) {emptyItem.add(i); }
        }
        
        for (Integer i: emptyItem) {
            int idx = i;
            itemHpp.getItemBonuses().remove(idx);
        }
        
        boolean saved = false;
        try{
            saved = ServicesList.getItemHppService().save(itemHpp);
            
        } catch(Exception ex){
            java.util.logging.Logger.getLogger(ItemHppFrm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            JOptionPane.showMessageDialog(this, "Data gagal disimpan.", "Error",JOptionPane.ERROR_MESSAGE);
        }
        
        initButtonState(!saved);
        
        //reload
        if (saved) {
            showStartDates(itemHpp.getId().getStartDate());
        }
    }
            
    public void validasi(){
        boolean valid;
        
        valid = itemHpp.getId().getItemId() > 0 ? true:false;
        if (valid) {valid = itemHpp.getId().getSupplierId() > 0 ? true:false; }
        if (valid) {valid = itemHpp.getId().getStartDate() != null ? true:false; }
        if (valid) {valid = itemHpp.getUnit().getId() > 0 ? true:false; }
        
        if (!valid) {
            JOptionPane.showMessageDialog(this, "Inputan blm lengkap.!"
            ,"Warning",JOptionPane.WARNING_MESSAGE);}
        
        if (valid) { saveData(); }
    }
    
    private void loadData() {
        
        if(itemHpp.getId().getItemId() > 0 && itemHpp.getId().getSupplierId() > 0 && 
                StringUtils.stringToDate((String)cmbDateHist.getSelectedItem()) != null) {
            
            ItemHpp dummyHpp = new ItemHpp();
            dummyHpp.getId().setStartDate(StringUtils.stringToDate((String)cmbDateHist.getSelectedItem()));
            dummyHpp.getId().setItemId(itemHpp.getId().getItemId());
            dummyHpp.getId().setSupplierId(itemHpp.getId().getSupplierId());
            dummyHpp = ServicesList.getItemHppService().get(dummyHpp.getId());
            if (dummyHpp !=null) {
                itemHpp = dummyHpp;            
                
                supplier = ServicesList.getSupplierService().getSupplier(itemHpp.getId().getSupplierId());
                txtDiskon.setText(StringUtils.formatNumber(itemHpp.getDiskon()));
                txtFraksi.setText(itemHpp.getFraksi().toString());
                txtTop.setText(itemHpp.getTop().toString());
                txtHarga.setText(StringUtils.formatNumber(itemHpp.getPrice()));
                txtItemName.setText(itemHpp.getItem().getNama());
                txtHpp.setText(StringUtils.formatNumber(itemHpp.getHpp()));
                txtKode.setText(itemHpp.getItem().getPlu());
                txtNet.setText(StringUtils.formatNumber(itemHpp.getHppAfterPpn()));
                txtPpn.setText(StringUtils.formatNumber(itemHpp.getPpn()));
                txtSpl.setText(supplier.getKode());
                txtSuplierName.setText(supplier.getNama());
                txtUnit.setText(itemHpp.getUnit().getKode());
                cmbKondisi.setSelectedIndex(NameValueList.indexOf(statusList, itemHpp.getKondisiBarang()));
                dtpStartDate.setDate(itemHpp.getId().getStartDate());
                System.out.println(itemHpp.getId().getStartDate());
                
                if (itemHpp.getItemDiskons().isEmpty()) {itemHpp.getItemDiskons().add(new ItemDiskon(DiskonType.PERSENTASE.toString())); }
                if (itemHpp.getItemBonuses().isEmpty()) { itemHpp.getItemBonuses().add(new ItemBonus()); }
                
                initGrid();
                initButtonState(false);
            }
        }
    }
    
    private void calculate() {
        Date now = StringUtils.truncDate(new Date());
                
        String hppString = TextComponentUtils.getValueFromTextNumber(txtHarga);
        BigDecimal diskon = BigDecimal.ZERO;       
        BigDecimal harga = new BigDecimal(hppString);
        BigDecimal hpp;
        BigDecimal ppn = BigDecimal.ZERO;
                
        for (ItemDiskon disk: itemHpp.getItemDiskons()) {
            Date beginDate = StringUtils.truncDate(disk.getBeginDate());
            Date endDate = StringUtils.truncDate(disk.getEndDate());
            if((beginDate.compareTo(now)<=0) && (endDate.compareTo(now)>=0)) {
                String jenis = DiskonType.PERSENTASE.toString(); 
                if (disk.getJenis().equals(DiskonType.PERSENTASE.toString())) {
                    BigDecimal tmpHarga = harga.subtract(diskon);
                    BigDecimal tmpDiskon = disk.getDiskon().divide(Constants.PERSENT_DIVIDER, 3, RoundingMode.HALF_UP);
                    diskon = diskon.add(tmpHarga.multiply(tmpDiskon));

                } else { diskon = diskon.add(disk.getDiskon()); }
            }
        }
        
        hpp = harga.subtract(diskon);
        if (itemHpp.getPkp()) { ppn = hpp.multiply(Constants.TAX_MULTIPLYER); }
        
        txtDiskon.setText(StringUtils.formatNumber(diskon));
        txtHpp.setText(StringUtils.formatNumber(hpp));
        txtPpn.setText(StringUtils.formatNumber(ppn));
        txtNet.setText(StringUtils.formatNumber(hpp.add(ppn)));
        initButtonState(true);
    }
    
    private void lookupMaster(int purpose, String param) {
        Object object = null;
        if (purpose == Constants.LOOKUP_MAIN_SUPPLIER) {
            if (itemHpp.getItem()!=null) {
                Map<NameValueList, Object> filter = new HashMap<>();
                filter.put(new NameValueList("itemSupplier.id.itemId", Constants.OPERATOR_EQUAL), itemHpp.getItem().getId()); 
                
                if(!param.isEmpty()) { 
                    filter.put(new NameValueList("supplier.nama", Constants.OPERATOR_LIKE), "%"+param+"%"); }
            
                object = new LookupSimpleFrm().execute(purpose, filter);
            }
        } else { object = new LookupSimpleFrm().execute(purpose, param); }
        if (object != null) { setMaster(purpose, object); }
    }
    
    private void setMaster(int purpose, Object object) {
         if (object != null) {
            switch (purpose) {
                case Constants.LOOKUP_ITEM:
                    itemHpp.setItem(((Item) object));
                    txtKode.setText(itemHpp.getItem().getPlu());
                    txtItemName.setText(itemHpp.getItem().getNama());
                    itemHpp.getId().setItemId(itemHpp.getItem().getId());
                    showStartDates(null);
                    txtSpl.requestFocus();
                    break;
                    
                case Constants.LOOKUP_MAIN_SUPPLIER:
                    supplier = ((ItemSupplier) object).getSupplier();
                    txtSpl.setText(supplier.getKode());
                    itemHpp.getId().setSupplierId(supplier.getId());
                    txtSuplierName.setText(supplier.getNama());
                    if (supplier.getSuprincipal()!=null) {
                        itemHpp.setPkp(supplier.getSuprincipal().getPkp());
                        txtTop.setText(supplier.getSuprincipal().getTop().toString());
                        txtTop.setEditable(supplier.getSuprincipal().getOpenTop());
                        cmbKondisi.setSelectedIndex(NameValueList.indexOf(statusList, supplier.getSuprincipal().getKondisiBarang()));    
                    }
                    
                    showStartDates(null);
                    dtpStartDate.requestFocus();
                    break;
                    
                case Constants.LOOKUP_UNIT:
                    itemHpp.setUnit((Unit) object);
                    txtUnit.setText(itemHpp.getUnit().getNama());
                    txtFraksi.requestFocus();
                    break;
                    
                 case Constants.LOOKUP_HADIAH:
                    int row = gridBonus.getSelectedRow();
                    itemHpp.getItemBonuses().get(row).setHadiah((Hadiah) object);
                    break;   

                default: break;    
            }
        }
    }
    
    private void getMaster(int purpose, String kode) {
        switch (purpose) {
           case Constants.LOOKUP_ITEM:
               itemHpp.setItem(ServicesList.getItemService().getItem(kode));
               if (itemHpp.getItem() != null) {setMaster(purpose, itemHpp.getItem()); }
               else { lookupMaster(purpose, txtKode.getText()); }
               break;
               
           case Constants.LOOKUP_MAIN_SUPPLIER:
               ItemSupplier itemSupplier = ServicesList.getItemSupplierService().get(itemHpp.getId().getItemId(), kode);
               if (itemSupplier != null) {setMaster(purpose, itemSupplier); }
               else { lookupMaster(purpose, txtSpl.getText()); }
               break;
               
           case Constants.LOOKUP_UNIT:
               itemHpp.setUnit(ServicesList.getUnitService().getUnit(kode));
               if (itemHpp.getUnit() != null) {
                   setMaster(purpose, itemHpp.getUnit());
               }else { lookupMaster(purpose, txtUnit.getText()); }
               break;
               
           case Constants.LOOKUP_HADIAH:    
                int row = gridBonus.getSelectedRow();

                if (itemHpp.getItemBonuses().get(row).getJenisBonus().equals(JenisBonus.BPB.toString())) {
        
                    Object object = new LookupSimpleFrm().execute(purpose, "");
                    if (object != null) { setMaster(purpose, object); }
                }
                break;
               
           default: break;    
        }
    }
    
    private void initButtonState(boolean status){
        btnSave.setEnabled(status);
    }
    
    private void deleteRowDiskon () {
        int rowCount = gridDiskon.getRowCount();
        int row = gridDiskon.getSelectedRow();
        
        if (rowCount==1) {
            itemHpp.getItemDiskons().add(new ItemDiskon(DiskonType.PERSENTASE.toString()));
            diskonTM.fireTableRowsUpdated(row, row);
        } else {
            itemHpp.getItemDiskons().remove(row);
            diskonTM.fireTableRowsDeleted(row, row);
        }
        calculate();
      //  initInputState();
        initButtonState(true);
    }
    
    private int getActivePriceIdx(Date selectedDate) {
        Date curdate = StringUtils.truncDate(new Date());
        for (int i=0; i<cmbDateHist.getItemCount(); i++) {
            if (selectedDate==null) {
                Date startDate = StringUtils.stringToDate((String) cmbDateHist.getItemAt(i));
                if (startDate.compareTo(curdate) <= 0) {
                    return i;
                }
            } else {
                if (selectedDate.compareTo(selectedDate) == 0) {
                    return i;
                }
            }
        }
        return -1;
    }
    
    private void showStartDates(Date startDate) {
        if (itemHpp.getId().getItemId()>0 && itemHpp.getId().getSupplierId()>0) {
            cmbDateHist.removeItemListener(itemListener);
            cmbDateHist.setModel(new DefaultComboBoxModel());
            List<Date> dates = ServicesList.getItemHppService().getDates(
                    itemHpp.getId().getItemId(), itemHpp.getId().getSupplierId());
            
            DefaultComboBoxModel cbModel = new DefaultComboBoxModel();
            for (Date date : dates) { cbModel.addElement(StringUtils.formatDate(date)); }
            cmbDateHist.setModel(cbModel);
            if(cbModel.getSize()==1) {loadData();}
            else if(cbModel.getSize()>1) {
                int priceActive = getActivePriceIdx(startDate);

                if (priceActive > -1) {
                    cmbDateHist.setSelectedIndex(priceActive);
                    loadData();
                }
            }
            cmbDateHist.addItemListener(itemListener);
        }    
    }
    
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        txtKode = new javax.swing.JTextField();
        txtSpl = new javax.swing.JTextField();
        dtpStartDate = new com.toedter.calendar.JDateChooser();
        txtTop = new javax.swing.JTextField();
        txtHarga = new javax.swing.JTextField();
        txtUnit = new javax.swing.JTextField();
        txtFraksi = new javax.swing.JTextField();
        txtDiskon = new javax.swing.JTextField();
        txtHpp = new javax.swing.JTextField();
        txtPpn = new javax.swing.JTextField();
        txtNet = new javax.swing.JTextField();
        txtItemName = new javax.swing.JTextField();
        txtSuplierName = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        jLabel8 = new javax.swing.JLabel();
        jLabel9 = new javax.swing.JLabel();
        cmbKondisi = new javax.swing.JComboBox();
        jPanel1 = new javax.swing.JPanel();
        jLabel11 = new javax.swing.JLabel();
        jLabel12 = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        gridDiskon = new javax.swing.JTable();
        jScrollPane1 = new javax.swing.JScrollPane();
        gridBonus = new javax.swing.JTable();
        jLabel10 = new javax.swing.JLabel();
        jToolBar1 = new javax.swing.JToolBar();
        btnNew = new javax.swing.JButton();
        btnCopy = new javax.swing.JButton();
        btnSave = new javax.swing.JButton();
        btnDelete = new javax.swing.JButton();
        jLabel13 = new javax.swing.JLabel();
        jLabel14 = new javax.swing.JLabel();
        jLabel15 = new javax.swing.JLabel();
        cmbDateHist = new javax.swing.JComboBox();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        txtKode.setName("txtKode"); // NOI18N

        txtSpl.setName("txtSpl"); // NOI18N

        dtpStartDate.setDateFormatString("dd/MM/yyyy");
        dtpStartDate.setName("dtpStartDate"); // NOI18N

        txtTop.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtTop.setName("txtTop"); // NOI18N

        txtHarga.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtHarga.setName("txtHarga"); // NOI18N

        txtUnit.setName("txtUnit"); // NOI18N

        txtFraksi.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtFraksi.setName("txtFraksi"); // NOI18N

        txtDiskon.setEditable(false);
        txtDiskon.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtDiskon.setFocusable(false);
        txtDiskon.setName("txtDiskon"); // NOI18N

        txtHpp.setEditable(false);
        txtHpp.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtHpp.setFocusable(false);
        txtHpp.setName("txtHpp"); // NOI18N

        txtPpn.setEditable(false);
        txtPpn.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtPpn.setFocusable(false);
        txtPpn.setName("txtPpn"); // NOI18N

        txtNet.setEditable(false);
        txtNet.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtNet.setFocusable(false);
        txtNet.setName("txtNet"); // NOI18N

        txtItemName.setEditable(false);
        txtItemName.setFocusable(false);
        txtItemName.setName("txtItemName"); // NOI18N

        txtSuplierName.setEditable(false);
        txtSuplierName.setFocusable(false);
        txtSuplierName.setName("txtSuplierName"); // NOI18N

        jLabel1.setText("PLU :");

        jLabel2.setText("Main Supplier :");

        jLabel3.setText("Start Date :");

        jLabel4.setText("Harga Beli :");

        jLabel5.setText("Satuan Beli :");

        jLabel6.setText("Diskon :");

        jLabel7.setText("PPN :");

        jLabel8.setText("HPP :");

        jLabel9.setText("HPP + PPN :");

        cmbKondisi.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        cmbKondisi.setName("cmbKondisi"); // NOI18N
        cmbKondisi.setNextFocusableComponent(gridDiskon);

        jLabel11.setText("DISKON");

        jLabel12.setText("BONUS");

        gridDiskon.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {},
                {},
                {},
                {}
            },
            new String [] {

            }
        ));
        gridDiskon.setName("gridDiskon"); // NOI18N
        jScrollPane2.setViewportView(gridDiskon);

        gridBonus.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {},
                {}
            },
            new String [] {

            }
        ));
        gridBonus.setName("gridBonus"); // NOI18N
        gridBonus.getTableHeader().setReorderingAllowed(false);
        jScrollPane1.setViewportView(gridBonus);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 516, Short.MAX_VALUE)
            .addComponent(jScrollPane1)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel11)
                    .addComponent(jLabel12))
                .addGap(0, 0, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addComponent(jLabel11)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 108, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jLabel12)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 88, Short.MAX_VALUE)
                .addGap(2, 2, 2))
        );

        jLabel10.setText("Kondisi Barang :");

        jToolBar1.setFloatable(false);
        jToolBar1.setRollover(true);
        jToolBar1.setMaximumSize(new java.awt.Dimension(32767, 20));
        jToolBar1.setSize(this.getWidth(), 50);

        btnNew.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edit_add.png"))); // NOI18N
        btnNew.setText("Tambah");
        btnNew.setFocusable(false);
        btnNew.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnNew.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnNew.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnNewActionPerformed(evt);
            }
        });
        jToolBar1.add(btnNew);

        btnCopy.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edit_remove.png"))); // NOI18N
        btnCopy.setText("Copy");
        btnCopy.setFocusable(false);
        btnCopy.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnCopy.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(btnCopy);

        btnSave.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edit.png"))); // NOI18N
        btnSave.setText("Save");
        btnSave.setFocusable(false);
        btnSave.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnSave.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSaveActionPerformed(evt);
            }
        });
        jToolBar1.add(btnSave);

        btnDelete.setText("Delete");
        btnDelete.setFocusable(false);
        btnDelete.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnDelete.setName("btnDelete"); // NOI18N
        btnDelete.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnDelete.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnDeleteActionPerformed(evt);
            }
        });
        jToolBar1.add(btnDelete);

        jLabel13.setText("TOP Buying :");

        jLabel14.setText("Hari");

        jLabel15.setText("Date Hist :");

        cmbDateHist.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        cmbDateHist.setName("cmbDateHist"); // NOI18N

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 675, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addGap(2, 2, 2)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(jLabel15)
                            .addComponent(jLabel2)
                            .addComponent(jLabel1)
                            .addComponent(jLabel10)
                            .addComponent(jLabel9)
                            .addComponent(jLabel7)
                            .addComponent(jLabel8)
                            .addComponent(jLabel6)
                            .addComponent(jLabel4)
                            .addComponent(jLabel13)
                            .addComponent(jLabel3)
                            .addComponent(jLabel5))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                .addComponent(cmbKondisi, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addGroup(layout.createSequentialGroup()
                                    .addComponent(txtUnit, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(txtFraksi, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE))
                                .addComponent(txtDiskon)
                                .addComponent(txtHpp)
                                .addComponent(txtPpn)
                                .addComponent(txtNet)
                                .addComponent(dtpStartDate, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(cmbDateHist, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(txtSpl)
                                .addComponent(txtKode, javax.swing.GroupLayout.DEFAULT_SIZE, 104, Short.MAX_VALUE)
                                .addComponent(txtHarga))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(txtTop, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jLabel14)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(txtSuplierName, javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(txtItemName)
                            .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(17, 17, 17)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(txtKode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(txtItemName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(txtSpl, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(txtSuplierName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel2))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(cmbDateHist, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel15))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(dtpStartDate, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel3))
                        .addGap(5, 5, 5)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtTop, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel14)
                            .addComponent(jLabel13))
                        .addGap(4, 4, 4)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtHarga, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel4))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtUnit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(txtFraksi, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel5))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtDiskon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel6))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtHpp, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel8))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtPpn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel7))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtNet, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel9))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(cmbKondisi, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel10)))
                    .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(63, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btnNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNewActionPerformed
        initForm();
        txtKode.requestFocus();
    }//GEN-LAST:event_btnNewActionPerformed

    private void btnSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSaveActionPerformed
        validasi();
    }//GEN-LAST:event_btnSaveActionPerformed

    private void btnDeleteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeleteActionPerformed
        deleteRowDiskon();
    }//GEN-LAST:event_btnDeleteActionPerformed
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnCopy;
    private javax.swing.JButton btnDelete;
    private javax.swing.JButton btnNew;
    private javax.swing.JButton btnSave;
    private javax.swing.JComboBox cmbDateHist;
    private javax.swing.JComboBox cmbKondisi;
    private com.toedter.calendar.JDateChooser dtpStartDate;
    private javax.swing.JTable gridBonus;
    private javax.swing.JTable gridDiskon;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel13;
    private javax.swing.JLabel jLabel14;
    private javax.swing.JLabel jLabel15;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JTextField txtDiskon;
    private javax.swing.JTextField txtFraksi;
    private javax.swing.JTextField txtHarga;
    private javax.swing.JTextField txtHpp;
    private javax.swing.JTextField txtItemName;
    private javax.swing.JTextField txtKode;
    private javax.swing.JTextField txtNet;
    private javax.swing.JTextField txtPpn;
    private javax.swing.JTextField txtSpl;
    private javax.swing.JTextField txtSuplierName;
    private javax.swing.JTextField txtTop;
    private javax.swing.JTextField txtUnit;
    // End of variables declaration//GEN-END:variables

    @Override
    public void setVisible(boolean value) {
        super.setVisible(value);
        txtKode.requestFocusInWindow();
    }
    
    private void moveNext() {
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.focusNextComponent();
    }
    
    class ActionKeyListener implements KeyListener {
        @Override public void keyTyped(KeyEvent e) {} 
        @Override public void keyReleased(KeyEvent e) {}
        @Override public void keyPressed(KeyEvent e) {
            switch (e.getKeyCode()) { 
                case KeyEvent.VK_F2: 
                    switch(e.getComponent().getName()) {
                        case "txtKode": lookupMaster(Constants.LOOKUP_ITEM, txtKode.getText()); break;
                        case "txtSpl": lookupMaster(Constants.LOOKUP_MAIN_SUPPLIER, txtSpl.getText()); break;
                        case "txtUnit": lookupMaster(Constants.LOOKUP_UNIT, txtUnit.getText()); break;
                        case "bonusItemCellEditor": lookupMaster(Constants.LOOKUP_HADIAH, bonusItemCellEditor.getText()); break;
                    };
                break;  
                
                case KeyEvent.VK_ENTER: 
                    switch(e.getComponent().getName()) {
                        case "txtKode": 
                            newValue = txtKode.getText();
                            if (!newValue.equals(oldValue)) { getMaster(Constants.LOOKUP_ITEM, newValue.toString()); }
                            else {moveNext();}
                            break;
                            
                        case "txtSpl": 
                            newValue = txtSpl.getText();
                            if (!newValue.equals(oldValue)) { getMaster(Constants.LOOKUP_MAIN_SUPPLIER, newValue.toString()); }
                            else {moveNext();}
                            break;
                            
                        case "dtpStartDate": 
                            newValue = dtpStartDate.getDate();
                            if (!newValue.equals(oldValue)) { 
                                itemHpp.getId().setStartDate(StringUtils.truncDate(dtpStartDate.getDate()));
                            }
                            moveNext(); break;
                            
                        case "txtUnit": 
                            newValue = txtUnit.getText();
                            if (!newValue.equals(oldValue)) { getMaster(Constants.LOOKUP_UNIT, txtUnit.getText()); }
                            else {moveNext();}
                            break;
                            
                        case "txtHarga": 
                            newValue = txtHarga.getText();
                            if (!newValue.equals(oldValue)) { calculate(); }
                            moveNext(); break;    
                        
                        case "bonusItemCellEditor": 
                            newValue = bonusItemCellEditor.getText();
                            if (!newValue.equals(oldValue)) { getMaster(Constants.LOOKUP_UNIT, bonusItemCellEditor.getText()); }
                            else {moveNext();}
                            break;
                                
                       default: moveNext(); break;
                    };
                break;      
            }
        }
    }
    
    class ActionFocusGained implements FocusListener {
        @Override public void focusGained(FocusEvent e) { 
            Component componen = (Component) e.getSource(); 
            if (componen instanceof JTextField) { oldValue = ((JTextField) componen).getText();
            }else if (componen instanceof JComboBox) { oldValue = ((JComboBox) componen).getSelectedIndex();
            }else if (componen instanceof JCheckBox) { oldValue = ((JCheckBox) componen).isSelected();
            }else if (componen instanceof JTextArea) { oldValue = ((JTextArea) componen).getText(); 
            }else if (componen instanceof JDateChooser) { oldValue = ((JDateChooser) componen).getDate(); }
        }
        
        @Override public void focusLost(FocusEvent e) {
            Component componen = (Component) e.getSource(); 
            if (componen instanceof JTextField) { newValue = ((JTextField) componen).getText();
            }else if (componen instanceof JComboBox) { newValue = ((JComboBox) componen).getSelectedIndex();
            }else if (componen instanceof JCheckBox) { newValue = ((JCheckBox) componen).isSelected();
            }else if (componen instanceof JTextArea) { newValue = ((JTextArea) componen).getText(); 
            }else if (componen instanceof JDateChooser) { newValue = ((JDateChooser) componen).getDate(); }
            
            if (!newValue.equals(oldValue)) { initButtonState(true); }
        }
    }
    
    //GRID DISKON
    class GridDiskonActionListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            if ("JComboBox".equals(e.getSource().getClass().getSimpleName())) {
                int idx =  gridDiskon.getSelectedRow();
                String jenis = ((NameValueList) cmbDiskonJenis.getSelectedItem()).getKey();
                itemHpp.getItemDiskons().get(idx).setJenis(jenis);
            }    
            calculate();
        }
    }
    
    class GridDiskonKeyListener implements KeyListener {
        @Override public void keyTyped(KeyEvent e) {};
        @Override public void keyReleased(KeyEvent e) {};
        
        @Override public void keyPressed(KeyEvent e) {
            switch (e.getKeyCode()) { 
                case KeyEvent.VK_ENTER:
                    if ((gridDiskon.getSelectedRow() == gridDiskon.getRowCount()-1) 
                            && gridDiskon.getSelectedColumn() == gridDiskon.getColumnCount()-1) {
                        itemHpp.getItemDiskons().add(new ItemDiskon(DiskonType.PERSENTASE.toString()));
                            diskonTM.fireTableDataChanged(); 
                    }
                    calculate();
                    break;
            }        
        };
    }

    //GRID BONUS
    class gridBonusActionListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            int idx =  gridBonus.getSelectedRow();
            if (gridBonus.getSelectedColumn() == COL_BONUS_HITUNG) {
                String jenis = ((NameValueList) cmbBonusHitung.getSelectedItem()).getKey();
                itemHpp.getItemBonuses().get(idx).setCaraHitung(jenis);
            }else if (gridBonus.getSelectedColumn() == COL_BONUS_SATUAN) {
                String jenis = ((NameValueList) cmbBonusSatuan.getSelectedItem()).getKey();
                itemHpp.getItemBonuses().get(idx).setSatuanBonus(jenis);
            }else if (gridBonus.getSelectedColumn() == COL_BONUS_JENIS) {
                String jenis = ((NameValueList) cmbBonusJenis.getSelectedItem()).getKey();
                itemHpp.getItemBonuses().get(idx).setJenisBonus(jenis);
            }
            initButtonState(true);
        }
    }
    
    class StartDatesListener implements ItemListener {
        @Override
        public void itemStateChanged(ItemEvent e) {
            if(e.getStateChange()==ItemEvent.SELECTED) {
                loadData();
            }
        }
    }
    
    private void initComponentsRules() {
        btnNew.registerKeyboardAction(btnNew.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, false)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, false), JComponent.WHEN_FOCUSED);
 
        btnNew.registerKeyboardAction(btnNew.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, true)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, true), JComponent.WHEN_FOCUSED);
        
        btnCopy.registerKeyboardAction(btnCopy.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, false)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, false), JComponent.WHEN_FOCUSED);

        btnCopy.registerKeyboardAction(btnCopy.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, true)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, true), JComponent.WHEN_FOCUSED);

        btnSave.registerKeyboardAction(btnSave.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, false)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, false), JComponent.WHEN_FOCUSED);
 
        btnSave.registerKeyboardAction(btnSave.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, true)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, true), JComponent.WHEN_FOCUSED);
        
        TextComponentUtils.setNumericTextOnly(txtFraksi);
        TextComponentUtils.setCurrency(txtHarga);

        txtDiskon.addKeyListener(new ActionKeyListener());
        txtFraksi.addKeyListener(new ActionKeyListener());
        txtHarga.addKeyListener(new ActionKeyListener());
        txtItemName.addKeyListener(new ActionKeyListener());
        txtHpp.addKeyListener(new ActionKeyListener());
        txtKode.addKeyListener(new ActionKeyListener());
        txtNet.addKeyListener(new ActionKeyListener());
        txtPpn.addKeyListener(new ActionKeyListener());
        txtSpl.addKeyListener(new ActionKeyListener());
        txtSuplierName.addKeyListener(new ActionKeyListener());
        txtUnit.addKeyListener(new ActionKeyListener());
        txtTop.addKeyListener(new ActionKeyListener());
        cmbKondisi.addKeyListener(new ActionKeyListener());

        txtDiskon.addFocusListener(new ActionFocusGained());
        txtFraksi.addFocusListener(new ActionFocusGained());
        txtHarga.addFocusListener(new ActionFocusGained());
        txtItemName.addFocusListener(new ActionFocusGained());
        txtHpp.addFocusListener(new ActionFocusGained());
        txtKode.addFocusListener(new ActionFocusGained());
        txtNet.addFocusListener(new ActionFocusGained());
        txtPpn.addFocusListener(new ActionFocusGained());
        txtSpl.addFocusListener(new ActionFocusGained());
        txtSuplierName.addFocusListener(new ActionFocusGained());
        txtUnit.addFocusListener(new ActionFocusGained());
        txtTop.addFocusListener(new ActionFocusGained());
        cmbKondisi.addFocusListener(new ActionFocusGained());
                
        dtpStartDate.getDateEditor().addPropertyChangeListener(
            new PropertyChangeListener() {
            @Override public void propertyChange(PropertyChangeEvent evt) {
                if ("date".equals(evt.getPropertyName())) {
                    if(!evt.getNewValue().equals(evt.getOldValue())) {
                        itemHpp.getId().setStartDate(StringUtils.truncDate((Date) evt.getNewValue()));
                        initButtonState(true);
                    }
                }
            }
        });
   
        cmbKondisi.setModel(ComponentUtils.getDefaultComboBoxModel(statusList));
        TableUtil.setTableActionKeyMap(gridDiskon);
        cmbDiskonJenis.addActionListener(new GridDiskonActionListener());
        diskonCellEditor.addActionListener(new GridDiskonActionListener());
        gridDiskon.addKeyListener( new GridDiskonKeyListener());
        
        TableUtil.setTableActionKeyMap(gridBonus);
        cmbBonusHitung.addActionListener(new gridBonusActionListener());
        cmbBonusSatuan.addActionListener(new gridBonusActionListener());
        cmbBonusJenis.addActionListener(new gridBonusActionListener());
        
        bonusItemCellEditor.setName("bonusItemCellEditor");
        bonusItemCellEditor.addKeyListener(new ActionKeyListener());
        bonusItemCellEditor.addFocusListener(new ActionFocusGained());
        
        MaskFormatter dateMask;
        try {
            dateMask = new MaskFormatter("##/##/####");
               dateMask.install(diskonEndDateCellEditor);
               dateMask.install(diskonStartDateCellEditor);
               dateMask.install(bonusStartDateCellEditor);
               dateMask.install(bonusEndDateCellEditor);
        } catch (ParseException ex) { log.error(ex); }
        
        cmbDateHist.setModel(new DefaultComboBoxModel());
    }      
    
    private void setTableLookStyle() {
        
    }
    
}    
